package org.reenscape;
import org.reenscape.lib.*;
import org.reenscape.updater.*;
import org.reenscape.auth.*;
import org.reenscape.sock.*;
import org.reenscape.model.*;
import org.reenscape.remote.*;
import java.io.*;
/**
* Basically the core of the server. Controls everything that the server can do.
@author Jim
@version 1.5
*/
public class Server {

	/**
	* The time that the server has between cycles. 500 = Half second.
	*/
	public static final int LoopTime = 500;
	/**
	* The number of loops the server has gone through. Used in diagnostics.
	*/
	public static int Loops = 0;
	
	/**
	* Flags the server to close the logins if it needs to update.
	*/
	public static boolean updateServer = false;
	
	/**
	* Amount of time left for the update. (Server-wide)
	*/
	public static int updateSeconds = 180;
	/**
	* Milliseconds from start of the cycle.
	*/
	public static long startTime;
	
	/**
	* The thread that the client listener runs on.
	*/
	public static Thread accepterThread = null;

	/**
	* Main method that starts  all of the classes doing their jobs.
	*/
	public static void main(java.lang.String args[]) {
	
		System.out.println("ReenScape Shift - Created by Jim and the ReenScapeShift.com team");
		System.out.println("Booting up...");
	
		accepter = new ClientAccepter();
		accepterThread = new Thread(accepter);
		clientUpdater = new ClientUpdater();
		npcUpdater = new NpcUpdater();
		itemHandler = new ItemUpdater();
		shopHandler = new ShopUpdater();
		objectUpdater = new ObjectUpdater();
		dialogueHandler = new DialogueUpdater();
		loginAuth = new LoginAuth();
		PlayerCount.go();
		Status.go();
		try{
		new Configuration().LoadConfig();
		} catch(Exception e) {System.out.println("Configuration failed to load - exiting."); System.exit(1);}
		
		
		MySQL.connect(Configuration.MySQLUsername, Configuration.MySQLPassword, Configuration.MySQLAddress, Configuration.MySQLPort, Configuration.MySQLDatabase);

		new Startup();
		
		int waitFails = 0;
		long lastTicks = System.currentTimeMillis();
		long totalTimeSpentProcessing = 0;
		int cycle = 0;
		while(!shutdownServer) {
			if(updateServer)
				calcTime();
				clientUpdater.process();
				npcUpdater.process();
				itemHandler.process();
				shopHandler.process();
				objectUpdater.process();
				objectUpdater.firemaking_process();
				Graphics.process();
				System.gc();
				Loops++;
	
				long timeSpent = System.currentTimeMillis() - lastTicks;
				totalTimeSpentProcessing += timeSpent;
					if(timeSpent >= LoopTime) {
						timeSpent = LoopTime;
					}
					try {
						Thread.sleep(LoopTime-timeSpent);
					} catch(java.lang.Exception _ex) { }
						lastTicks = System.currentTimeMillis();
						cycle++;
					if(cycle % 100 == 0){ float time = ((float)totalTimeSpentProcessing)/cycle; }
					if(cycle % 3600 == 0) System.gc();
					if (ShutDown == true) {
						if (ShutDownCounter >= 100) {
							shutdownServer = true;
						}
					ShutDownCounter++;
					}
		}
		clientUpdater.destruct();
		accepter.kill();
		accepter = null;
	}

	/**
	* Listener that accepts connections on the socket.
	*/
	public static ClientAccepter accepter = null;
	
	/**
	* Flag that stops this from going through the process loop.
	*/
	public static boolean shutdownServer = false;

	/**
	* Where all the players currently on are controlled.
	*/
	public static ClientUpdater clientUpdater = null;
	
	/**
	* Where every NPC regardless if it's static or not is handled.
	*/
	public static NpcUpdater npcUpdater = null;
	
	/**
	* Controlls all of the items on the ground.
	*/
	public static ItemUpdater itemHandler = null;
	
	/**
	* Shop controlls.
	*/
	public static ShopUpdater shopHandler = null;
	
	/**
	* Handles state for doors and fires.
	*/
	public static ObjectUpdater objectUpdater = null;
	
	/**
	* Dialogue scripting.
	*/
	public static DialogueUpdater dialogueHandler = null;
	
	/**
	* Checks the SQL tables for correct authorization. Bans, password and username, locked accounts, etc.
	*/
	public static LoginAuth loginAuth = null;
	
	/**
	* Calculates the time that the loop went through.
	*/
	public static void calcTime() {
		long curTime = System.currentTimeMillis();
		updateSeconds = 180 - ((int)(curTime - startTime) / 1000);
		if(updateSeconds == 0) {
			shutdownServer = true;
		}
	}

	/**
	* Energy that it starts at.
	*/
	public static int EnergyRegian = 60;
	
	/**
	* Signals shut down.
	*/
	public static boolean ShutDown = false;
	
	/**
	* Counts the amount of the shut down time.
	*/
	public static int ShutDownCounter = 0;
	
	/**
	* Max item ID.
	*/
	public static int MaxItems = 7840;
	
	/**
	* Adds an IP to the blacklist for null connections.
	*/
	public static void blacklist(String ip){
		BufferedWriter bw = null;
		try {
			bw = new BufferedWriter(new FileWriter("../local/blacklist.txt", true));
			bw.write(ip);
			bw.newLine();
			bw.flush();
		} catch (IOException ioe) {} 
		finally {
			if (bw != null) 
				try {
					bw.close();
				} catch (IOException ioe2) {}
		}
    }
}